WOLF core
WOLF: A Modular Estimation Framework for Robotics
XXXXXXXXXXXXXXXXXXXXXXXXvoid(0)" frameborder="0" name="MSearchResults" id="MSearchResults">
composite.h
Go to the documentation of this file.
1// WOLF - Copyright (C) 2020-2026
2// Institut de Robòtica i Informàtica Industrial, CSIC-UPC.
3// Authors: Joan Solà Ortega (jsola@iri.upc.edu) and
4// Joan Vallvé Navarro (jvallve@iri.upc.edu)
5// All rights reserved.
6//
7// This file is part of WOLF: http://www.iri.upc.edu/wolf
8// WOLF is free software: you can redistribute it and/or modify
9// it under the terms of the GNU General Public License version 3
10// as published by the Free Software Foundation.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program. If not, see <http://www.gnu.org/licenses/>.
19#pragma once
20
21#include "core/common/wolf.h"
22#include <string>
23#include <map>
24#include <algorithm>
25#include "yaml-cpp/yaml.h"
26
27namespace wolf
28{
29using std::map;
30
31typedef std::string StateKeys;
32
33static std::string ALL_KEYS = " ";
34
38StateKeys keysUnion(const StateKeys& _keys1, const StateKeys& _keys2);
39
43StateKeys keysIntersection(const StateKeys& _keys1, const StateKeys& _keys2);
44
45template <typename T>
46class Composite : public map<char, T>
47{
48 public:
49 using CompositeType = T;
50
51 using map<char, T>::map;
52 Composite(const YAML::Node& _n,
53 const std::string& _field,
54 const bool _required,
55 const std::string& _keys = ALL_KEYS);
56 virtual ~Composite() = default;
57
58 bool has(char _key) const;
59 bool has(const StateKeys& _structure) const;
61
62 friend std::ostream& operator<<(std::ostream& _os, const Composite<T>& _x)
63 {
64 for (auto&& pair : _x)
65 {
66 _os << pair.first << ": " << pair.second << std::endl;
67 }
68 return _os;
69 }
70
71 Composite operator()(const std::string& _keys) const;
72
73 YAML::Node toYaml() const;
74};
75
77
78template <typename T>
79inline Composite<T>::Composite(const YAML::Node& _n,
80 const std::string& _field,
81 const bool _required,
82 const std::string& _keys)
83{
84 if (_n.IsDefined())
85 {
86 if (not _n.IsMap())
87 {
88 throw std::runtime_error("Composite: constructor with a non-map yaml node");
89 }
90
91 // check existence of _keys in node
92 if (_keys != ALL_KEYS)
93 for (auto key : _keys)
94 if (not _n[key] and _required)
95 {
96 throw std::runtime_error(std::string("Composite ") + typeid(T).name() +
97 " constructor: Missing node for key '" + key + "'.");
98 }
99
100 // iterate node map pairs
101 for (auto node_pair : _n)
102 {
103 // check that keys are char type
104 char key;
105 try
106 {
107 key = node_pair.first.as<char>();
108 }
109 catch (const std::exception& e)
110 {
111 throw std::runtime_error(std::string("In Composite ") + typeid(T).name() +
112 " constructor: There is a key of type different than char: " +
113 node_pair.first.as<std::string>() + ". Error: " + e.what());
114 }
115
116 // discard if not in _keys (if _keys is not ALL_KEYS)
117 if (_keys != ALL_KEYS and //
118 _keys.find(key) == std::string::npos) //
119 continue;
120
121 // check field
122 if (not _field.empty())
123 {
124 if (node_pair.second[_field])
125 {
126 try
127 {
128 this->emplace(key, node_pair.second[_field].as<T>());
129 }
130 catch (const std::exception& e)
131 {
132 YAML::Emitter em;
133 em << node_pair.second[_field];
134 throw std::runtime_error("In Composite constructor: Failed to emplace the entry " + _field +
135 " for key '" + key + "' with error: " + e.what() + "\nNode:\n" +
136 em.c_str());
137 }
138 }
139 else if (_required)
140 {
141 YAML::Emitter em;
142 em << node_pair.second;
143 throw std::runtime_error("In Composite constructor: Missing mandatory field '" + _field +
144 "' for key '" + key + "'\nNode:\n" + em.c_str());
145 }
146 }
147 else
148 {
149 try
150 {
151 this->emplace(key, node_pair.second.as<T>());
152 }
153 catch (const std::exception& e)
154 {
155 YAML::Emitter em;
156 em << node_pair.second;
157 throw std::runtime_error("In Composite constructor: Failed to emplace the entry for key '" +
158 std::string(1, key) + "' with error: " + e.what() + "\nNode:\n" +
159 em.c_str());
160 }
161 }
162 }
163 }
164 else
165 {
166 WOLF_WARN("The YAML node is not defined. Constructing an empty composite");
167 }
168}
169
170template <typename T>
171inline bool Composite<T>::has(char _key) const
172{
173 return this->count(_key) != 0;
174}
175
176template <typename T>
177inline bool Composite<T>::has(const StateKeys& _query_keys) const
178{
179 for (auto&& key : _query_keys)
180 {
181 if (not has(key))
182 {
183 return false;
184 }
185 }
186 return true;
187}
188
189template <typename T>
191{
192 StateKeys keys;
193 for (auto&& pair : *this) keys.push_back(pair.first);
194
195 return keys;
196}
197
198template <typename T>
199inline Composite<T> Composite<T>::operator()(const std::string& _keys) const
200{
201 if (not this->has(_keys))
202 {
203 throw std::runtime_error("Composite<T>::operator() required keys " + _keys + " are not available, only have " +
204 getKeys());
205 }
206
207 Composite<T> output;
208 for (auto key : _keys)
209 {
210 output.emplace(key, this->at(key));
211 }
212 return output;
213}
214
215template <typename T>
216inline YAML::Node Composite<T>::toYaml() const
217{
218 return YAML::Node(*this);
219}
220
221} // namespace wolf
222
223// CONVERSION TO YAML
224namespace YAML
225{
226template <typename T>
227struct convert<wolf::Composite<T>>
228{
229 static Node encode(const wolf::Composite<T>& composite)
230 {
231 Node n;
232 for (auto&& pair : composite)
233 {
234 n[pair.first] = pair.second;
235 }
236
237 return n;
238 }
239
240 static bool decode(const Node& node, wolf::Composite<T>& composite)
241 {
242 composite = wolf::Composite<T>(node);
243
244 return true;
245 }
246};
247} // namespace YAML
Definition: composite.h:47
Composite(const YAML::Node &_n, const std::string &_field, const bool _required, const std::string &_keys=ALL_KEYS)
Definition: composite.h:79
StateKeys getKeys() const
Definition: composite.h:190
bool has(const StateKeys &_structure) const
Definition: composite.h:177
T CompositeType
Definition: composite.h:49
virtual ~Composite()=default
Composite operator()(const std::string &_keys) const
Definition: composite.h:199
friend std::ostream & operator<<(std::ostream &_os, const Composite< T > &_x)
Definition: composite.h:62
YAML::Node toYaml() const
Definition: composite.h:216
bool has(char _key) const
Definition: composite.h:171
#define WOLF_WARN(...)
Definition: logging.h:436
Definition: composite.h:225
Definition: capture_base.h:23
std::string StateKeys
Definition: composite.h:31
static std::string ALL_KEYS
Definition: composite.h:33
Composite< bool > BoolComposite
Definition: composite.h:76
StateKeys keysIntersection(const StateKeys &_keys1, const StateKeys &_keys2)
Intersection of two sets of keys: the keys of _keys1 that are also in _keys2, in the order of _keys1 ...
Definition: composite.cpp:31
StateKeys keysUnion(const StateKeys &_keys1, const StateKeys &_keys2)
Union of two sets of keys: the keys of _keys1 followed by the keys of _keys2 not in _keys1 (no duplic...
Definition: composite.cpp:23
static Node encode(const wolf::Composite< T > &composite)
Definition: composite.h:229
static bool decode(const Node &node, wolf::Composite< T > &composite)
Definition: composite.h:240